package com.jfinal.generator.model;

import com.jfinal.plugin.activerecord.dialect.*;
import com.jfinal.plugin.druid.DruidPlugin;

import javax.sql.DataSource;
import java.util.List;

/**
 * GeneratorDemo
 */
public class GeneratorModel {

    private String dataSource_url;
    private String dataSource_username;
    private String dataSource_password;
    // model 所使用的包名 (MappingKit 默认使用的包名)
    private String modelPackageName;
    // base model 所使用的包名
    private String baseModelPackageName;
    // base model 文件保存路径
    private String baseModelOutputDir;
    // model 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径)
    private String modelOutputDir;

    private MetaBuilder metaBuilder;
    private BaseModelGenerator baseModelGenerator;
    private ModelGenerator modelGenerator;
    private MappingKitGenerator mappingKitGenerator;
    private DataDictionaryGenerator dataDictionaryGenerator;

    public GeneratorModel(String dataSource_url, String dataSource_username, String dataSource_password, String modelPackageName) {
        this.dataSource_url = dataSource_url;
        this.dataSource_username = dataSource_username;
        this.dataSource_password = dataSource_password;
        this.modelPackageName = modelPackageName;
        this.baseModelPackageName = modelPackageName + ".base";
        this.baseModelOutputDir = System.getProperty("user.dir") + "/src/main/java/" + baseModelPackageName.replace('.', '/');
        this.modelOutputDir = baseModelOutputDir + "/..";
    }

    public DataSource getDataSource() {
        String dataSource_driveClass = getDriveClass(dataSource_url);
        DruidPlugin druidPlugin = new DruidPlugin(dataSource_url, dataSource_username, dataSource_password, dataSource_driveClass);
        druidPlugin.start();
        return druidPlugin.getDataSource();
    }

    public void generate(String... table) {
        this.metaBuilder = new MetaBuilder(getDataSource());
        this.baseModelGenerator = new BaseModelGenerator(baseModelPackageName, baseModelOutputDir);
        this.modelGenerator = new ModelGenerator(modelPackageName, baseModelPackageName, modelOutputDir);
        this.mappingKitGenerator = new MappingKitGenerator(modelGenerator.modelPackageName, modelGenerator.modelOutputDir);
        this.dataDictionaryGenerator = new DataDictionaryGenerator(getDataSource(), modelGenerator.modelOutputDir);
        metaBuilder.setDialect(getDialect(dataSource_url));
        metaBuilder.setTable(table);
        // 生成
        long start = System.currentTimeMillis();
        List<TableMeta> tableMetas = metaBuilder.build();
        if (tableMetas.size() == 0) {
            System.out.println("TableMeta 数量为 0，不生成任何文件");
            return;
        }
        baseModelGenerator.generate(tableMetas);
        if (modelGenerator != null) {
            modelGenerator.generate(tableMetas);
        }
        if (mappingKitGenerator != null) {
            mappingKitGenerator.generate(tableMetas);
        }
        if (dataDictionaryGenerator != null) {
            dataDictionaryGenerator.generate(tableMetas);
        }
        long usedTime = (System.currentTimeMillis() - start) / 1000;
        System.out.println("Generate complete in " + usedTime + " seconds.");
    }

    private Dialect getDialect(String dataSource_url) {
        if (dataSource_url.contains("postgresql")) {
            return new PostgreSqlDialect();
        } else if (dataSource_url.contains("sqlserver")) {
            return new SqlServerDialect();
        } else if (dataSource_url.contains("oracle")) {
            return new OracleDialect();
        } else if (dataSource_url.contains("sqlite")) {
            return new Sqlite3Dialect();
        } else if (dataSource_url.contains("mysql")) {
            return new MysqlDialect();
        } else {
            return new AnsiSqlDialect();
        }
    }

    private String getDriveClass(String dataSource_url) {
        if (dataSource_url.contains("postgresql")) {
            return "org.postgresql.Driver";
        } else if (dataSource_url.contains("sqlserver")) {
            return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
        } else if (dataSource_url.contains("oracle")) {
            return "oracle.jdbc.OracleDriver";
        } else if (dataSource_url.contains("sqlite")) {
            return "org.sqlite.JDBC";
        } else if (dataSource_url.contains("mysql")) {
            return "com.mysql.cj.jdbc.Driver";
        } else {
            return "null";
        }
    }

}
